home *** CD-ROM | disk | FTP | other *** search
- /* Internet FTP client (interactive user)
- * Copyright 1991 Phil Karn, KA9Q
- */
- /* Mods by G1EMM and PA0GRI */
- /* modifications for encrypted password by ik1che 900419 */
- /* added "resume" and "rput" commands for interrupted file transfers
- * by iw0cnb 15 Feb 92 */
-
- #include <stdio.h>
- #include "global.h"
- #include "config.h"
- #include "mbuf.h"
- #include "session.h"
- #include "cmdparse.h"
- #include "proc.h"
- #include "tty.h"
- #include "socket.h"
- #include "ftp.h"
- #include "ftpcli.h"
- #include "commands.h"
- #include "netuser.h"
- #include "dirutil.h"
- #include "help.h"
- #ifdef LZW
- #include "lzw.h"
- #endif
-
- #define DIRBUF 256
-
- extern char *FTPHelp; /* FTP Help file */
-
- #ifdef ALLSESSIONS
- static int doascii __ARGS((int argc,char *argv[],void *p));
- static int dobatch __ARGS((int argc,char *argv[],void *p));
- static int dobinary __ARGS((int argc,char *argv[],void *p));
- static int docompare __ARGS((int argc,char *argv[],void *p));
- static int doftpcd __ARGS((int argc,char *argv[],void *p));
- static int doftpcdup __ARGS((int argc,char *argv[],void *p));
- static int doftpdel __ARGS((int argc,char *argv[],void *p));
- static int doget __ARGS((int argc,char *argv[],void *p));
- static int dohash __ARGS((int argc,char *argv[],void *p));
- static int doverbose __ARGS((int argc,char *argv[],void *p));
- static int dolist __ARGS((int argc,char *argv[],void *p));
- static int dols __ARGS((int argc,char *argv[],void *p));
- static int domd5 __ARGS((int argc,char *argv[],void *p));
- static int doldir __ARGS((int argc,char *argv[],void *p));
- static int dolcd __ARGS((int argc,char *argv[],void *p));
- static int dolmkdir __ARGS((int argc,char *argv[],void *p));
- static int dolrename __ARGS((int argc,char *argv[],void *p));
- static int dolrmdir __ARGS((int argc,char *argv[],void *p));
- static int domcompare __ARGS((int argc,char *argv[],void *p));
- static int domkdir __ARGS((int argc,char *argv[],void *p));
- static int domget __ARGS((int argc,char *argv[],void *p));
- static int domput __ARGS((int argc,char *argv[],void *p));
- static int doput __ARGS((int argc,char *argv[],void *p));
- static int dopwd __ARGS((int argc,char *argv[],void *p));
- static int doftphelp __ARGS((int argc,char *argv[],void *p));
- static int doquit __ARGS((int argc,char *argv[],void *p));
- static int dormdir __ARGS((int argc,char *argv[],void *p));
- static int dorename __ARGS((int argc,char *argv[],void *p));
- static int doresume __ARGS((int argc,char *argv[],void *p));
- static int dorput __ARGS((int argc,char *argv[],void *p));
- static int dotype __ARGS((int argc,char *argv[],void *p));
- static int getline __ARGS((struct session *sp,char *prompt,char *buf,int n));
- static int getresp __ARGS((struct ftpcli *ftp,int mincode));
- static int doupdate __ARGS((int argc,char *argv[],void *p));
- static long getsub __ARGS((struct ftpcli *ftp,char *command,char *remotename,
- char *localname));
- static long putsub __ARGS((struct ftpcli *ftp,char *remotename,char *localname,int putr));
- static void sendport __ARGS((int s,struct sockaddr_in *socket));
-
- static char Notsess[] = "Not an FTP session!\n";
- static int Ftp_type = ASCII_TYPE;
- static int Ftp_logbsize = 8;
-
- static struct cmds DFAR Ftpcmds[] = {
- "", donothing, 0, 0, NULLCHAR,
- "?", doftphelp, 0, 0, NULLCHAR,
- "append", doput, 0, 2, "append <localfile> <remotefile>",
- "ascii", doascii, 0, 0, NULLCHAR,
- "batch", dobatch, 0, 0, NULLCHAR,
- "binary", dobinary, 0, 0, NULLCHAR,
- "bye", doquit, 0, 0, NULLCHAR,
- "cd", doftpcd, 0, 2, "cd <directory>",
- "cdup", doftpcdup, 0, 0, NULLCHAR,
- "compare", docompare, 0, 2, "compare <remotefile> [<localfile>]",
- "del", doftpdel, 0, 2, "del <remotefile>",
- "dir", dolist, 0, 0, NULLCHAR,
- "exit", doquit, 0, 0, NULLCHAR,
- "get", doget, 0, 2, "get <remotefile> <localfile>",
- "hash", dohash, 0, 0, NULLCHAR,
- "help", doftphelp, 0, 0, NULLCHAR,
- "lcd", dolcd, 0, 1, NULLCHAR,
- "ldir", doldir, 0, 1, NULLCHAR,
- "list", dolist, 0, 0, NULLCHAR,
- "lmkdir", dolmkdir, 0, 2, "lmkdir <local Directory>",
- "lrename", dolrename, 0, 3, "lrename <oldname> <newname>",
- "lrmdir", dolrmdir, 0, 2, "lrmdir <local Directory>",
- "ls", dols, 0, 0, NULLCHAR,
- #ifdef LZW
- "lzw", dolzw, 0, 0, NULLCHAR,
- #endif
- "mcompare", domcompare, 0, 2, "mcompare <file> [<file> ...]",
- "md", domkdir, 0, 2, "md <directory>",
- "md5", domd5, 0, 2, "md5 <file>",
- "mget", domget, 0, 2, "mget <file> [<file> ...]",
- "mkdir", domkdir, 0, 2, "mkdir <directory>",
- "mput", domput, 0, 2, "mput <file> [<file> ...]",
- "nlst", dols, 0, 0, NULLCHAR,
- "put", doput, 0, 2, "put <localfile> <remotefile>",
- "pwd", dopwd, 0, 0, NULLCHAR,
- "quit", doquit, 0, 0, NULLCHAR,
- "rename", dorename, 0, 3, "rename <oldname> <newname>",
- "resume", doresume, 0, 2, "resume <remotefile> <localfile>",
- "rmdir", dormdir, 0, 2, "rmdir <directory>",
- "rput", dorput, 0, 2, "rput <localfile> <remotefile>",
- "type", dotype, 0, 0, NULLCHAR,
- "update", doupdate, 0, 0, NULLCHAR,
- "verbose", doverbose, 0, 0, NULLCHAR,
- NULLCHAR, NULLFP, 0, 0, NULLCHAR,
- };
-
-
- int
- doftphelp(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- dohelper ("FTP commands:\n", &Ftpcmds[1], NULLCHAR, (argv[0][0] == '?' && argc == 1) ? NULLCHAR : FTPHelp, (argc == 2) ? argv[1] : NULLCHAR);
- return 0;
- }
-
- /* Handle top-level FTP command */
- int
- doftp(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct session *sp;
- struct ftpcli ftp;
- struct sockaddr_in fsocket;
- int resp,vsave;
- char *buf,*bufsav,*cp,*un;
- char prmt[40];
- char l[17];
- int control;
- char *ftpcli_login();
- FILE *fp1 = NULLFILE;
- struct cur_dirs dirs;
-
- /*Make sure this comes from console - WG7J*/
- if(Curproc->input != Command->input)
- return 0;
-
- /* Allocate a session control block */
- if((sp = newsession(argv[1],FTP,0)) == NULLSESSION){
- tputs(TooManySessions);
- return 1;
- }
- memset((char *)&ftp,0,sizeof(ftp));
- ftp.control = ftp.data = -1;
- ftp.verbose = V_BYTE; /* changed to ver 4 default - KO4KS */
- ftp.type = Ftp_type;
- ftp.logbsize = Ftp_logbsize;
-
- sp->cb.ftp = &ftp; /* Downward link */
- ftp.session = sp; /* Upward link */
-
- ftp.curdirs = &dirs;
-
- fsocket.sin_family = AF_INET;
- fsocket.sin_port = IPPORT_FTP;
-
- tprintf("Resolving %s... ",sp->name);
- if((fsocket.sin_addr.s_addr = resolve(sp->name)) == 0){
- tprintf(Badhost,sp->name);
- keywait(NULLCHAR,1);
- freesession(sp);
- return 1;
- }
- /* Open the control connection */
- if((control = sp->s = ftp.control = socket(AF_INET,SOCK_STREAM,0)) == -1){
- tputs(Nosock);
- keywait(NULLCHAR,1);
- freesession(sp);
- return 1;
- }
- sockmode(sp->s,SOCK_ASCII);
- setflush(sp->s,-1); /* Flush output only when we call getresp() */
- tprintf("Trying %s...\n",psocket((struct sockaddr *)&fsocket));
- tprintf("Local Directory - %s\n",init_dirs(&dirs));
- if(connect(control,(char *)&fsocket,sizeof(fsocket)) == -1)
- goto quit;
- tprintf("FTP session %u connected to %s\n",(unsigned)(sp-Sessions),
- sp->name);
-
- /* Wait for greeting from server */
- resp = getresp(&ftp,200);
-
- if(resp >= 400)
- goto quit;
- un = getenv("USER");
- if(un != NULLCHAR)
- sprintf(prmt,"Enter user name (%s): ",un);
- else
- sprintf(prmt,"Enter user name: ");
- /* Now process responses and commands */
- buf = mallocw(LINELEN);
-
- if(argc > 2)
- if((fp1 = fopen(argv[2],READ_TEXT)) == NULLFILE) goto quit;
- while(resp != -1){
- switch (resp) {
- case 220: /* Sign-on banner; prompt for and send USER command */
- if((cp = ftpcli_login(&ftp, sp->name)) == NULLCHAR) {
- if(argc > 2) {
- if(fgets(buf,LINELEN,fp1) == NULLCHAR)
- goto quit;
- } else
- getline(sp,prmt,buf,LINELEN);
- /* Send the command only if the user response
- * was non-null
- */
- if(buf[0] != '\n') {
- usprintf(control,"USER %s",buf);
- resp = getresp(&ftp,200);
- } else {
- if(un != NULLCHAR) {
- usprintf(control,"USER %s\n",un);
- resp = getresp(&ftp,200);
- } else {
- tprintf("No username sent\n");
- resp = 200; /* dummy */
- }
- }
- } else {
- usprintf(control,"USER %s\n",cp);
- free(cp);
- resp = getresp(&ftp,200);
- }
- break;
- case 331: if(ftp.password == NULLCHAR) {
- /* turn off echo */
- if(argc > 2) {
- if(fgets(buf,LINELEN,fp1) == NULLCHAR)
- goto quit;
- } else {
- sp->ttystate.echo = 0;
- getline(sp,"Password: ",buf,LINELEN);
- tprintf("\n");
- /* Turn echo back on */
- sp->ttystate.echo = 1;
- }
- /* Send the command only if the user response
- * was non-null
- */
- if(buf[0] != '\n') {
- usprintf(control,"PASS %s",buf);
- resp = getresp(&ftp,200);
- } else {
- tprintf("Password must be provided.\nLoggin failed.\n");
- resp = 200; /* dummy */
- }
- } else {
- usprintf(control,"PASS %s\n",ftp.password);
- resp = getresp(&ftp,200);
- free(ftp.password);
- ftp.password = NULLCHAR; /* clean up */
- }
- break;
- case 230: /* Successful login */
- /* Find out what type of system we're talking to */
- tprintf("ftp> syst\n");
- usprintf(control,"SYST\n");
- resp = getresp(&ftp,200);
- break;
- case 215: /* Response to SYST command */
- cp = strchr(ftp.line,' ');
- if(cp != NULLCHAR && strnicmp(cp+1,System,strlen(System)) == 0){
- ftp.type = IMAGE_TYPE;
- tprintf("Defaulting to binary mode\n");
- }
- resp = 200; /* dummy */
- break;
- #ifdef notyet
- case 399: /* Encrypted password login */
- if(ftp.password == NULLCHAR) {
- getline(sp,"Key ? --> ",buf,LINELEN);
- /* Send the command only if the user response
- * was non-null
- */
- if(buf[0] != '\n') {
- cp = strchr(ftp.line,':');
- cp += 2;
- /*
- epass(htol(cp),buf,l);
- */
- l[16] = '\0';
- free(ftp.line);
- ftp.line = NULLCHAR;
- usprintf(control,"PASS %s\n",l);
- resp = getresp(&ftp,200);
- } else {
- tprintf("Password must be provided.\nLogin failed.\n");
- resp = 200; /* dummy */
- }
- } else {
- cp = strchr(ftp.line,':');
- cp += 2;
- /*
- epass(htol(cp),ftp.password,l);
- */
- l[16] = '\0';
- free(ftp.line);
- ftp.line = NULLCHAR;
- usprintf(control,"PASS %s\n",l);
- resp = getresp(&ftp,200);
- free(ftp.password);
- ftp.password = NULLCHAR; /* clean up */
- }
- break;
- #endif
- default: /* Test the control channel first */
- if(sockstate(control) == NULLCHAR)
- break;
- if(argc > 2) {
- if(fgets(buf,LINELEN,fp1) == NULLCHAR)
- goto quit;
- } else
- getline(sp,"ftp> ",buf,LINELEN);
-
- /* Copy because cmdparse modifies the original */
- bufsav = strdup(buf);
- if((resp = cmdparse(Ftpcmds,buf,&ftp)) != -1) {
- /* Valid command, free buffer and get another */
- free(bufsav);
- } else {
- /* Not a local cmd, send to remote server */
- usputs(control,bufsav);
- free(bufsav);
-
- /* Enable display of server response */
- vsave = ftp.verbose;
- ftp.verbose = V_NORMAL;
- resp = getresp(&ftp,200);
- ftp.verbose = vsave;
- }
- }
- }
- free(buf);
- quit: cp = sockerr(control);
- tprintf("FTP session %u closed: %s\n",(unsigned)(sp - Sessions),
- cp != NULLCHAR ? cp : "EOF");
-
- if(ftp.fp != NULLFILE && ftp.fp != stdout)
- fclose(ftp.fp);
- if(ftp.data != -1)
- close_s(ftp.data);
- if(ftp.control != -1)
- close_s(ftp.control);
- if(argc < 3)
- keywait(NULLCHAR,1);
- else
- fclose(fp1);
- if(ftp.session != NULLSESSION)
- freesession(ftp.session);
- free_dirs(&dirs);
- return 0;
- }
-
-
- /* Control verbosity level */
- static int
- doverbose(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- register struct ftpcli *ftp;
-
- if((ftp = (struct ftpcli *)p) == NULLFTP)
- return -1;
- return setshort(&ftp->verbose,"Verbose",argc,argv);
- }
- /* Enable/disable command batching */
- static int
- dobatch(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- register struct ftpcli *ftp;
-
- if((ftp = (struct ftpcli *)p) == NULLFTP)
- return -1;
- return setbool(&ftp->batch,"Command batching",argc,argv);
- }
- /* Enable/disable update flag */
- static int
- doupdate(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- register struct ftpcli *ftp;
-
- if((ftp = (struct ftpcli *)p) == NULLFTP)
- return -1;
- return setbool(&ftp->update,"Update with MD5",argc,argv);
- }
- /* Set verbosity to high (convenience command) */
- static int
- dohash(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- register struct ftpcli *ftp;
-
- if((ftp = (struct ftpcli *)p) == NULLFTP)
- return -1;
- tputs("Hash Printing ");
- if (ftp->verbose==V_HASH){
- ftp->verbose = V_HASH+1;
- tputs("Off\n");
- } else {
- tputs("On\n");
- ftp->verbose = V_HASH;
- }
- return 0;
- }
-
- /* Close session */
- static int
- doquit(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- register struct ftpcli *ftp;
-
- ftp = (struct ftpcli *)p;
- if(ftp == NULLFTP)
- return -1;
- usprintf(ftp->control,"QUIT\n");
- getresp(ftp,200); /* Get the closing message */
- getresp(ftp,200); /* Wait for the server to close */
- return -1;
- }
-
- #ifdef LZW
- /* Toggle LZW compressed streams mode on */
- static int
- dolzw(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- register struct ftpcli *ftp;
- int retval;
-
- ftp = (struct ftpcli *)p;
- if(ftp == NULLFTP)
- return -1;
- if (ftp->lzw) {
- tprintf ("550 Already using LZW compression\n");
- return (550);
- }
- usprintf(ftp->control,"XLZW %d %d\n", Lzwbits, Lzwmode);
- retval = getresp(ftp,200);
- if (retval >= 200 && retval < 300) {
- ftp->lzw = 1;
- ftp->lzwbits = Lzwbits;
- ftp->lzwmode = Lzwmode;
- /* lzwinit (ftp->control, Lzwbits, Lzwmode); */
- }
- return (retval);
- }
- #endif
-
- /* Rename remote file */
- static int
- dorename(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- register struct ftpcli *ftp;
- int retval;
-
- ftp = (struct ftpcli *)p;
- if(ftp == NULLFTP)
- return -1;
- usprintf(ftp->control,"RNFR %s\n", argv[1]);
- retval = getresp(ftp,350);
-
- if (retval != 350)
- return (retval);
- usprintf(ftp->control,"RNTO %s\n", argv[2]);
- return (getresp(ftp,200));
- }
-
- /* Rename local file */
- static int
- dolrename(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- register struct ftpcli *ftp;
- char fname1[128];
- char fname2[128];
-
- ftp = (struct ftpcli *)p;
- if(ftp == NULLFTP)
- return -1;
- strcpy(fname1,make_fname(ftp->curdirs->dir,argv[1]));
- strcpy(fname2,make_fname(ftp->curdirs->dir,argv[2]));
- if(rename(fname1,fname2) == -1)
- tprintf("Can't rename: %s\n",sys_errlist[errno]);
- else
- tprintf("Local file renamed to '%s'\n",fname2);
- return 0;
-
- }
-
- static int
- txlate (argc,argv,p,substr, parm)
- int argc;
- char *argv[];
- void *p;
- char *substr;
- int parm;
- {
- register struct ftpcli *ftp;
-
- ftp = (struct ftpcli *)p;
- if(ftp == NULLFTP)
- return -1;
- usprintf(ftp->control,"%s %s\n",substr, (parm) ? argv[1] : "");
- return getresp(ftp,200);
- }
-
- /* Pass PWD to server - included here to allow cmd to be viewed in help list */
- static int
- dopwd(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return (txlate (argc, argv, p, "PWD", 0));
- }
-
- /* Translate 'cd' to 'cwd' for convenience */
- static int
- doftpcd(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- if (argc == 1)
- return (dopwd(argc, argv, p));
- return (txlate (argc, argv, p, "CWD", 1));
- }
-
- /* Pass CDUP to server - included here to allow cmd to be viewed in help list */
- static int
- doftpcdup(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return (txlate (argc, argv, p, "CDUP", 0));
- }
-
- /* Translate 'del' to 'dele' for convenience */
- static int
- doftpdel(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return (txlate (argc, argv, p, "DELE", 1));
- }
-
- /* Translate 'mkdir' to 'xmkd' for convenience */
- static int
- domkdir(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return (txlate (argc, argv, p, "XMKD", 1));
- }
- /* Translate 'rmdir' to 'xrmd' for convenience */
- static int
- dormdir(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return (txlate (argc, argv, p, "XRMD", 1));
- }
- static int
- dobinary(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- char *args[2];
-
- args[1] = "I";
- return dotype(2,args,p);
- }
- static int
- doascii(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- char *args[2];
-
- args[1] = "A";
- return dotype(2,args,p);
- }
-
- /* Handle "type" command from user */
- static int
- dotype(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- register struct ftpcli *ftp;
-
- ftp = (struct ftpcli *)p;
- if(ftp == NULLFTP)
- return -1;
- if(argc < 2){
- switch(ftp->type){
- case IMAGE_TYPE:
- tprintf("Image\n");
- break;
- case ASCII_TYPE:
- tprintf("Ascii\n");
- break;
- case LOGICAL_TYPE:
- tprintf("Logical bytesize %u\n",ftp->logbsize);
- break;
- }
- return 0;
- }
- switch(*argv[1]){
- case 'i':
- case 'I':
- case 'b':
- case 'B':
- ftp->type = IMAGE_TYPE;
- break;
- case 'a':
- case 'A':
- ftp->type = ASCII_TYPE;
- break;
- case 'L':
- case 'l':
- ftp->type = LOGICAL_TYPE;
- ftp->logbsize = atoi(argv[2]);
- break;
- default:
- tprintf("Invalid type %s\n",argv[1]);
- return 1;
- }
- return 0;
- }
-
- /* Handle "ftype" command */
- int
- doftype(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- if(argc < 2){
- tprintf("Ftp initial TYPE is ");
- switch(Ftp_type){
- case IMAGE_TYPE:
- tprintf("Image\n");
- break;
- case ASCII_TYPE:
- tprintf("Ascii\n");
- break;
- case LOGICAL_TYPE:
- tprintf("Logical bytesize %u\n",Ftp_logbsize);
- break;
- }
- return 0;
- }
- switch(*argv[1]){
- case 'i':
- case 'I':
- case 'b':
- case 'B':
- Ftp_type = IMAGE_TYPE;
- break;
- case 'a':
- case 'A':
- Ftp_type = ASCII_TYPE;
- break;
- case 'L':
- case 'l':
- Ftp_type = LOGICAL_TYPE;
- Ftp_logbsize = atoi(argv[2]);
- break;
- default:
- tprintf("Invalid type %s\n",argv[1]);
- return 1;
- }
- return 0;
- }
-
- /* Start receive transfer. Syntax: get <remote name> [<local name>] */
- static int
- doget(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- char *remotename,*localname;
- register struct ftpcli *ftp;
-
- ftp = (struct ftpcli *)p;
- if(ftp == NULLFTP){
- tprintf(Notsess);
- return 1;
- }
- remotename = argv[1];
- if(argc < 3)
- localname = remotename;
- else
- localname = argv[2];
-
- if(!ftp->update || compsub(ftp,localname,remotename) != 0)
- getsub(ftp,"RETR",remotename,localname);
- return 0;
- }
- /* Get a collection of files */
- static int
- domget(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- register struct ftpcli *ftp;
- FILE *files, *filel;
- char tmpname[80];
- char *buf, *local, *c;
- int i, inlist;
- long r;
-
- if((ftp = (struct ftpcli *)p) == NULLFTP){
- tprintf(Notsess);
- return 1;
- }
- tmpnam(tmpname);
- buf = mallocw(DIRBUF);
- ftp->state = RECEIVING_STATE;
- for(i=1;i<argc;i++){
- if(argv[i][0] == '@'){
- inlist = 1;
- if((filel = fopen(make_fname(ftp->curdirs->dir,&argv[i][1]), "r")) == NULLFILE){
- tprintf("Can't open listfile: %s\n", &argv[i][1]);
- continue;
- }
- if((files = fopen(tmpname, "w")) == NULLFILE){
- tprintf("Can't open tempfile: %s\n", tmpname);
- continue;
- }
- while(fgets(buf,DIRBUF,filel) != NULLCHAR){
- fputs(buf,files);
- }
- fclose(files);
- fclose(filel);
- if((files = fopen(tmpname, "r")) == NULLFILE){
- tprintf("Can't open tempfile: %s\n", tmpname);
- continue;
- }
- } else {
- inlist = 0;
- r = getsub(ftp,"NLST",argv[i],tmpname);
- if(ftp->abort)
- break; /* Aborted */
- if(r == -1 || (files = fopen(tmpname,"r")) == NULLFILE){
- tprintf("Can't NLST %s\n",argv[i]);
- unlink(tmpname);
- continue;
- }
- }
- /* The tmp file now contains a list of the remote files, so
- * go get 'em. Break out if the user signals an abort.
- */
- while(fgets(buf,DIRBUF,files) != NULLCHAR){
- rip(buf);
- local = strdup(buf);
- #ifdef MSDOS
- if(inlist){
- strrev(local);
- strtok(local, "\\/[]<>,?#~()&%");
- strrev(local);
- }
- if((c = strstr(local, ".")) != NULLCHAR) {
- c++;
- c = strtok(c, "."); /* remove 2nd period if any*/
- }
- #endif
- if(!ftp->update || compsub(ftp,buf,buf) != 0)
- getsub(ftp,"RETR",buf,local);
- usflush (ftp->control);
- free(local);
- if(ftp->abort){
- /* User abort */
- ftp->abort = 0;
- fclose(files);
- unlink(tmpname);
- free(buf);
- ftp->state = COMMAND_STATE;
- return 1;
- }
- }
- fclose(files);
- unlink(tmpname);
- }
- free(buf);
- ftp->state = COMMAND_STATE;
- ftp->abort = 0;
- return 0;
- }
- /* Resume interrupted file transfer. Syntax: resume <remote name> [<local name>] */
- static int
- doresume(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- char *remotename,*localname;
- register struct ftpcli *ftp;
-
- ftp = (struct ftpcli *)p;
- if(ftp == NULLFTP){
- tprintf(Notsess);
- return 1;
- }
- remotename = argv[1];
- if(argc < 3)
- localname = remotename;
- else
- localname = argv[2];
-
- getsub(ftp,"RSME",remotename,localname);
- return 0;
- }
- /* List remote directory. Syntax: dir <remote files> [<local name>] */
- static int
- dolist(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- char *remotename,*localname;
- register struct ftpcli *ftp;
-
- ftp = (struct ftpcli *)p;
- if(ftp == NULLFTP){
- tprintf(Notsess);
- return 1;
- }
- remotename = argv[1];
- if(argc > 2)
- localname = argv[2];
- else
- localname = NULLCHAR;
-
- getsub(ftp,"LIST",remotename,localname);
- return 0;
- }
- /* Remote directory list, short form. Syntax: ls <remote files> [<local name>] */
- static int
- dols(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- char *remotename,*localname;
- register struct ftpcli *ftp;
-
- ftp = (struct ftpcli *)p;
- if(ftp == NULLFTP){
- tprintf(Notsess);
- return 1;
- }
- remotename = argv[1];
- if(argc > 2)
- localname = argv[2];
- else
- localname = NULLCHAR;
-
- getsub(ftp,"NLST",remotename,localname);
- return 0;
- }
- static int
- domd5(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- char *remotename;
- register struct ftpcli *ftp;
- int control;
- int resp;
- int typewait = 0;
-
- ftp = (struct ftpcli *)p;
- if(ftp == NULLFTP){
- tprintf(Notsess);
- return 1;
- }
- control = ftp->control;
- remotename = argv[1];
- if(ftp->typesent != ftp->type){
- switch(ftp->type){
- case ASCII_TYPE:
- usprintf(control,"TYPE A\n");
- break;
- case IMAGE_TYPE:
- usprintf(control,"TYPE I\n");
- break;
- case LOGICAL_TYPE:
- usprintf(control,"TYPE L %d\n",ftp->logbsize);
- break;
- }
- ftp->typesent = ftp->type;
- if(!ftp->batch){
- resp = getresp(ftp,200);
- if(resp == -1 || resp > 299)
- goto failure;
- } else
- typewait = 1;
-
- }
- usprintf(control,"XMD5 %s\n",remotename);
- if(typewait)
- (void)getresp(ftp,200);
- (void)getresp(ftp,200);
- failure:;
- return 0;
- }
- static int
- docompare(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- char *remotename,*localname;
- register struct ftpcli *ftp;
-
- ftp = (struct ftpcli *)p;
- if(ftp == NULLFTP){
- tprintf(Notsess);
- return 1;
- }
- remotename = argv[1];
- if(argc > 2)
- localname = argv[2];
- else
- localname = remotename;
-
- if(compsub(ftp,localname,remotename) == 0)
- tprintf("Same\n");
- else
- tprintf("Different\n");
- return 0;
- }
- /* Compare a collection of files */
- static int
- domcompare(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- register struct ftpcli *ftp;
- FILE *files;
- char *buf;
- int i;
- long r;
- char tmpname[80];
-
- if((ftp = (struct ftpcli *)p) == NULLFTP){
- tprintf(Notsess);
- return 1;
- }
- tmpnam(tmpname);
- buf = mallocw(DIRBUF);
- ftp->state = RECEIVING_STATE;
- for(i=1;i<argc;i++){
- r = getsub(ftp,"NLST",argv[i],tmpname);
- if(ftp->abort)
- break; /* Aborted */
- if(r == -1 || (files = fopen(tmpname,"r")) == NULLFILE){
- tprintf("Can't NLST %s\n",argv[i]);
- unlink(tmpname);
- continue;
- }
- /* The tmp file now contains a list of the remote files, so
- * go get 'em. Break out if the user signals an abort.
- */
- while(fgets(buf,DIRBUF,files) != NULLCHAR){
- rip(buf);
- if(compsub(ftp,buf,buf) == 0)
- tprintf("%s - Same\n",buf);
- else
- tprintf("%s - Different\n",buf);
-
- if(ftp->abort){
- /* User abort */
- ftp->abort = 0;
- fclose(files);
- unlink(tmpname);
- free(buf);
- ftp->state = COMMAND_STATE;
- return 1;
- }
- }
- fclose(files);
- unlink(tmpname);
- }
- free(buf);
- ftp->state = COMMAND_STATE;
- ftp->abort = 0;
- return 0;
- }
- /* Common subroutine to compare a local with a remote file
- * Return 1 if files are different, 0 if they are the same
- */
- static int
- compsub(ftp,localname,remotename)
- struct ftpcli *ftp;
- char *localname;
- char *remotename;
- {
- char *mode,*cp;
- FILE *fp;
- int control;
- int resp,i;
- int typewait = 0;
- char remhash[16];
- char lochash[16];
- char *file;
-
- control = ftp->control;
-
- switch(ftp->type){
- case IMAGE_TYPE:
- case LOGICAL_TYPE:
- mode = READ_BINARY;
- break;
- case ASCII_TYPE:
- mode = READ_TEXT;
- break;
- }
- if((fp = fopen(make_fname(ftp->curdirs->dir,localname),mode)) == NULLFILE){
- tprintf("Can't read local file %s\n",make_fname(ftp->curdirs->dir,localname));
- return 1;
- }
- if(ftp->typesent != ftp->type){
- switch(ftp->type){
- case ASCII_TYPE:
- usprintf(control,"TYPE A\n");
- break;
- case IMAGE_TYPE:
- usprintf(control,"TYPE I\n");
- break;
- case LOGICAL_TYPE:
- usprintf(control,"TYPE L %d\n",ftp->logbsize);
- break;
- }
- ftp->typesent = ftp->type;
- if(!ftp->batch){
- resp = getresp(ftp,200);
- if(resp == -1 || resp > 299)
- goto failure;
- } else
- typewait = 1;
- }
- usprintf(control,"XMD5 %s\n",remotename);
- /* Try to overlap the two MD5 operations */
- md5hash(fp,lochash,ftp->type == ASCII_TYPE);
- fclose(fp);
- if(typewait && (resp = getresp(ftp,200)) > 299)
- goto failure;
- if((resp = getresp(ftp,200)) > 299){
- if(resp == 500)
- ftp->update = 0; /* XMD5 not supported */
- goto failure;
- }
- if((cp = strchr(ftp->line,' ')) == NULLCHAR){
- tprintf("Error in response\n");
- goto failure;
- }
- /* Convert ascii/hex back to binary */
- readhex(remhash,cp,sizeof(remhash));
- if(ftp->verbose > 1){
- tprintf("Loc ");
- for(i=0;i<sizeof(lochash);i++)
- tprintf("%02x",lochash[i] & 0xff);
- tprintf(" %s\n",make_fname(ftp->curdirs->dir,localname));
- }
- if(memcmp(lochash,remhash,sizeof(remhash)) == 0)
- return 0;
- else
- return 1;
- failure:;
- return 1;
- }
-
-
- /* Common code to LIST/NLST/RETR/RSME and mget
- * Returns number of bytes received if successful
- * Returns -1 on error
- */
- static long
- getsub(ftp,command,remotename,localname)
- register struct ftpcli *ftp;
- char *command,*remotename,*localname;
- {
- unsigned long total;
- FILE *fp;
- int cnt,resp,i,control,savmode;
- char *mode;
- struct sockaddr_in lsocket;
- struct sockaddr_in lcsocket;
- int32 startclk,rate;
- int vsave;
- int typewait = 0;
- int prevstate;
- unsigned long starting;
-
- if(ftp == NULLFTP)
- return -1;
- control = ftp->control;
- savmode = ftp->type;
-
- switch(ftp->type){
- case IMAGE_TYPE:
- case LOGICAL_TYPE:
- if(strcmp(command,"RSME") == 0)
- mode = APPEND_BINARY;
- else
- mode = WRITE_BINARY;
- break;
- case ASCII_TYPE:
- if(strcmp(command,"RSME") == 0)
- mode = APPEND_TEXT;
- else
- mode = WRITE_TEXT;
- break;
- }
- /* Open the file */
- if(localname == NULLCHAR){
- fp = NULLFILE;
- } else if((fp = fopen(make_fname(ftp->curdirs->dir,localname),mode)) == NULLFILE){
- tprintf("Can't write %s: %s\n",localname,sys_errlist[errno]);
- return -1;
- }
- /* Open the data connection */
- ftp->data = socket(AF_INET,SOCK_STREAM,0);
- listen(ftp->data,0); /* Accept only one connection */
- prevstate = ftp->state;
- ftp->state = RECEIVING_STATE;
- #ifdef LZW
- if (ftp->lzw)
- lzwinit (ftp->data, ftp->lzwbits, ftp->lzwmode);
- #endif
-
- /* Send TYPE message, if necessary */
- if(strcmp(command,"LIST") == 0 || strcmp(command,"NLST") == 0){
- /* Directory listings are always in ASCII */
- ftp->type = ASCII_TYPE;
- }
- if(ftp->typesent != ftp->type){
- switch(ftp->type){
- case ASCII_TYPE:
- usprintf(control,"TYPE A\n");
- break;
- case IMAGE_TYPE:
- usprintf(control,"TYPE I\n");
- break;
- case LOGICAL_TYPE:
- usprintf(control,"TYPE L %d\n",ftp->logbsize);
- break;
- }
- ftp->typesent = ftp->type;
- if(!ftp->batch){
- resp = getresp(ftp,200);
- if(resp == -1 || resp > 299)
- goto failure;
- } else
- typewait = 1;
- }
- /* Send the PORT message. Use the IP address
- * on the local end of our control connection.
- */
- i = SOCKSIZE;
- getsockname(ftp->data,(char *)&lsocket,&i); /* Get port number */
- i = SOCKSIZE;
- getsockname(ftp->control,(char *)&lcsocket,&i);
- lsocket.sin_addr.s_addr = lcsocket.sin_addr.s_addr;
- sendport(control,&lsocket);
- if(!ftp->batch){
- /* Get response to PORT command */
- resp = getresp(ftp,200);
- if(resp == -1 || resp > 299)
- goto failure;
- }
- /* Generate the command to start the transfer */
- if(remotename != NULLCHAR)
- usprintf(control,"%s %s\n",command,remotename);
- else
- usprintf(control,"%s\n",command);
-
- if(ftp->batch){
- /* Get response to TYPE command, if sent */
- if(typewait){
- resp = getresp(ftp,200);
- if(resp == -1 || resp > 299)
- goto failure;
- }
- /* Get response to PORT command */
- resp = getresp(ftp,200);
- if(resp == -1 || resp > 299)
- goto failure;
- }
- /* Get the intermediate "150" response */
- resp = getresp(ftp,100);
- if(resp == -1 || resp >= 400)
- goto failure;
-
- /* Wait for the server to open the data connection */
- cnt = 0;
- accept(ftp->data,NULLCHAR,(int *)NULL);
- startclk = msclock();
-
- /* If output is to the screen, temporarily disable hash marking */
- vsave = ftp->verbose;
- if(vsave >= V_HASH && fp == NULLFILE)
- ftp->verbose = V_NORMAL;
- if(strcmp(command,"RSME") == 0){
- if((starting = getsize(fp)) == -1)
- starting = 0L;
- usprintf(control,"%lu %lu\n",starting,checksum(fp,starting));
- usflush(control);
- fseek(fp,starting,SEEK_SET);
- }
- total = recvfile(fp,ftp->data,ftp->type,(ftp->verbose >= V_HASH) ? ftp->verbose : 0);
- /* Immediately close the data connection; some servers (e.g., TOPS-10)
- * wait for the data connection to close completely before returning
- * the completion message on the control channel
- */
- close_s(ftp->data);
- ftp->data = -1;
-
- #ifdef CPM
- if(fp != NULLFILE && ftp->type == ASCII_TYPE)
- putc(CTLZ,fp);
- #endif
- if(fp != NULLFILE && fp != stdout)
- fclose(fp);
- if(remotename == NULLCHAR)
- remotename = "";
- if(total == -1){
- tprintf("%s %s: Error/abort during data transfer\n",command,remotename);
- } else if(ftp->verbose >= V_SHORT){
- startclk = msclock() - startclk;
- rate = 0;
- if(startclk != 0){ /* Avoid divide-by-zero */
- if(total < 4294967L){
- rate = (total*1000)/startclk;
- } else { /* Avoid overflow */
- rate = total/(startclk/1000);
- }
- }
- tprintf("%s %s: %lu bytes in %lu sec (%lu/sec)\n",
- command,remotename, total,startclk/1000,rate);
- }
- /* Get the "Sent" message */
- getresp(ftp,200);
-
- ftp->state = prevstate;
- ftp->verbose = vsave;
- ftp->type = savmode;
- return total;
-
- failure:
- /* Error, quit */
- if(fp != NULLFILE && fp != stdout)
- fclose(fp);
- close_s(ftp->data);
- ftp->data = -1;
- ftp->state = prevstate;
- ftp->type = savmode;
- return -1;
- }
- /* Send a file. Syntax: put <local name> [<remote name>] */
- static int
- doput(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- register struct ftpcli *ftp;
- char *remotename,*localname;
-
- if((ftp = (struct ftpcli *)p) == NULLFTP){
- tprintf(Notsess);
- return 1;
- }
- localname = argv[1];
- if(argc < 3)
- remotename = localname;
- else
- remotename = argv[2];
-
- if(!ftp->update || compsub(ftp,localname,remotename) != 0)
- putsub(ftp,remotename,localname,(*argv[0] == 'a') ? 2 : 0);
- return 0;
- }
- /* Put a collection of files */
- static int
- domput(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- register struct ftpcli *ftp;
- FILE *files;
- int i, j;
- char tmpname[80];
- char *buf, *file;
-
- if((ftp = (struct ftpcli *)p) == NULLFTP){
- tprintf(Notsess);
- return 1;
- }
- tmpnam(tmpname);
- if((files = fopen(tmpname,"w+")) == NULLFILE){
- tprintf("Can't list local files\n");
- unlink(tmpname);
- return 1;
- }
- for(i=1;i<argc;i++) {
- /* Use the path in the ftp client struct, since user may have done
- * a lcd command to change dir !
- */
- file = pathname(ftp->curdirs->dir,argv[i]);
- /* Shift everything back one byte, pathname returns with a leading '/'! */
- for(j=1;j<=strlen(file);j++)
- file[j-1] = file[j];
- getdir(file,0,files);
- free(file);
- }
-
- rewind(files);
- buf = mallocw(DIRBUF);
- ftp->state = SENDING_STATE;
- while(fgets(buf,DIRBUF,files) != NULLCHAR){
- rip(buf);
- if(!ftp->update || compsub(ftp,buf,buf) != 0)
- putsub(ftp,buf,buf,0);
- if(ftp->abort)
- break; /* User abort */
- usflush (ftp->control);
- }
- fclose(files);
- unlink(tmpname);
- free(buf);
- ftp->state = COMMAND_STATE;
- ftp->abort = 0;
- return 0;
- }
- /* Put a file, appending data to it - iw0cnb */
- static int
- dorput(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- register struct ftpcli *ftp;
- char *remotename,*localname;
-
- if((ftp = (struct ftpcli *)p) == NULLFTP){
- tprintf(Notsess);
- return 1;
- }
- localname = argv[1];
- if(argc < 3)
- remotename = localname;
- else
- remotename = argv[2];
-
- putsub(ftp,remotename,localname,1);
- return 0;
- }
- /* Common code to put, mput.
- * Returns number of bytes sent if successful
- * Returns -1 on error
- */
- static long
- putsub(ftp,remotename,localname,putr)
- register struct ftpcli *ftp;
- char *remotename,*localname;
- int putr; /* Flag: 0 if standard put, 1 if put with resume, if 2 append */
- {
- char *mode;
- int i,resp,control;
- unsigned long total;
- FILE *fp;
- struct sockaddr_in lsocket,lcsocket;
- int32 startclk,rate;
- int typewait = 0;
- int prevstate;
- char *line;
- unsigned long starting;
- unsigned long check, local_check;
-
- control = ftp->control;
- if(ftp->type == IMAGE_TYPE)
- mode = READ_BINARY;
- else
- mode = READ_TEXT;
-
- /* Open the file */
- if((fp = fopen(make_fname(ftp->curdirs->dir,localname),mode)) == NULLFILE){
- tprintf("Can't read %s: %s\n",localname,sys_errlist[errno]);
- return -1;
- }
- if(ftp->type == ASCII_TYPE && isbinary(fp)){
- tprintf("Warning: type is ASCII and %s appears to be binary\n",localname);
- }
- /* Open the data connection */
- ftp->data = socket(AF_INET,SOCK_STREAM,0);
- listen(ftp->data,0);
- prevstate = ftp->state;
- ftp->state = SENDING_STATE;
- #ifdef LZW
- if (ftp->lzw)
- lzwinit (ftp->data, ftp->lzwbits, ftp->lzwmode);
- #endif
-
- /* Send TYPE message, if necessary */
- if(ftp->typesent != ftp->type){
- switch(ftp->type){
- case ASCII_TYPE:
- usprintf(control,"TYPE A\n");
- break;
- case IMAGE_TYPE:
- usprintf(control,"TYPE I\n");
- break;
- case LOGICAL_TYPE:
- usprintf(control,"TYPE L %d\n",ftp->logbsize);
- break;
- }
- ftp->typesent = ftp->type;
-
- /* Get response to TYPE command */
- if(!ftp->batch){
- resp = getresp(ftp,200);
- if(resp == -1 || resp > 299){
- goto failure;
- }
- } else
- typewait = 1;
- }
- /* Send the PORT message. Use the IP address
- * on the local end of our control connection.
- */
- i = SOCKSIZE;
- getsockname(ftp->data,(char *)&lsocket,&i);
- i = SOCKSIZE;
- getsockname(ftp->control,(char *)&lcsocket,&i);
- lsocket.sin_addr.s_addr = lcsocket.sin_addr.s_addr;
- sendport(control,&lsocket);
- if(!ftp->batch){
- /* Get response to PORT command */
- resp = getresp(ftp,200);
- if(resp == -1 || resp > 299){
- goto failure;
- }
- }
- /* Generate the command to start the transfer */
- if(putr == 1)
- usprintf(control,"RPUT %s\n",remotename);
- else if (putr == 2)
- usprintf(control,"APPE %s\n",remotename);
- else
- usprintf(control,"STOR %s\n",remotename);
-
- if(ftp->batch){
- /* Get response to TYPE command, if sent */
- if(typewait){
- resp = getresp(ftp,200);
- if(resp == -1 || resp > 299){
- goto failure;
- }
- }
- /* Get response to PORT command */
- resp = getresp(ftp,200);
- if(resp == -1 || resp > 299){
- goto failure;
- }
- }
- /* Get the intermediate "150" response */
- resp = getresp(ftp,100);
- if(resp == -1 || resp >= 400){
- goto failure;
- }
-
- /* Wait for the data connection to open. Otherwise the first
- * block of data would go out with the SYN, and this may confuse
- * some other TCPs
- */
- accept(ftp->data,NULLCHAR,(int *)NULL);
-
- startclk = msclock();
-
- if(putr == 1){ /* Wait for file offset and checksum */
- line=mallocw(40);
- recvline(control,line,40);
- starting=atol(line);
- check = (unsigned long)atol(strchr(line,' '));
- free(line);
- local_check = checksum(fp,starting);
- if(ftp->verbose >= V_HASH)
- tprintf("Remote checksum: %lu - Local checksum: %lu - Offset: %lu\n",check,local_check,starting);
- check -= local_check;
- if(check != 0){
- tprintf("Can't send %s: files are different\n",localname);
- shutdown(ftp->data,1);
- getresp(ftp,200);
- goto failure;
- }
- }
-
- total = sendfile(fp,ftp->data,ftp->type,(ftp->verbose >= V_HASH) ? ftp->verbose : 0);
- close_s(ftp->data);
- ftp->data = -1;
- fclose(fp);
-
- /* Wait for control channel ack before calculating transfer time;
- * this accounts for transmitted data in the pipe.
- */
- getresp(ftp,200);
-
- if(total == -1){
- tprintf("STOR %s: Error/abort during data transfer\n",remotename);
- } else if(ftp->verbose >= V_SHORT){
- startclk = msclock() - startclk;
- rate = 0;
- if(startclk != 0){ /* Avoid divide-by-zero */
- if(total < 4294967L){
- rate = (total*1000)/startclk;
- } else { /* Avoid overflow */
- rate = total/(startclk/1000);
- }
- }
- tprintf("STOR %s: %lu bytes in %lu sec (%lu/sec)\n",
- remotename,total,startclk/1000,rate);
- }
- ftp->state = prevstate;
- return total;
-
- failure:
- /* Error, quit */
- fclose(fp);
- close_s(ftp->data);
- ftp->data = -1;
- ftp->state = prevstate;
- return -1;
- }
- /* Abort a GET or PUT operation in progress. Note: this will leave
- * the partial file on the local or remote system
- */
- int
- doabort(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- register struct session *sp;
- register struct ftpcli *ftp;
-
- sp = (struct session *)p;
- if(sp == NULLSESSION)
- return -1;
-
- /* Default is the current session, but it can be overridden with
- * an argument.
- */
- if(argc > 1)
- sp = sessptr(argv[1]);
-
- if(sp == NULLSESSION || sp->type != FTP){
- tprintf("Not an active FTP session\n");
- return 1;
- }
- ftp = sp->cb.ftp;
- switch(ftp->state){
- case COMMAND_STATE:
- tprintf("No active transfer\n");
- return 1;
- case SENDING_STATE:
- /* Send a premature EOF.
- * Unfortunately we can't just reset the connection
- * since the remote side might end up waiting forever
- * for us to send something.
- */
- shutdown(ftp->data,1); /* Note fall-thru */
- ftp->abort = 1;
- break;
- case RECEIVING_STATE:
- /* Just blow away the receive socket */
- shutdown(ftp->data,2); /* Note fall-thru */
- ftp->abort = 1;
- break;
- }
- return 0;
- }
- /* send PORT message */
- static void
- sendport(s,socket)
- int s;
- struct sockaddr_in *socket;
- {
- /* Send PORT a,a,a,a,p,p message */
- usprintf(s,"PORT %u,%u,%u,%u,%u,%u\n",
- hibyte(hiword(socket->sin_addr.s_addr)),
- lobyte(hiword(socket->sin_addr.s_addr)),
- hibyte(loword(socket->sin_addr.s_addr)),
- lobyte(loword(socket->sin_addr.s_addr)),
- hibyte(socket->sin_port),
- lobyte(socket->sin_port));
- }
-
- /* Wait for, read and display response from FTP server. Return the result code.
- */
- static int
- getresp(ftp,mincode)
- struct ftpcli *ftp;
- int mincode; /* Keep reading until at least this code comes back */
- {
- int rval;
-
- usflush(ftp->control);
- for(;;){
- /* Get line */
- if(recvline(ftp->control,ftp->line,LINELEN) == -1){
- rval = -1;
- break;
- }
- rip(ftp->line); /* Remove cr/lf */
- rval = atoi(ftp->line);
- if(rval >= 400 || ftp->verbose >= V_NORMAL)
- tprintf("%s\n",ftp->line); /* Display to user */
-
- /* Messages with dashes are continued */
- if(ftp->line[3] != '-' && rval >= mincode)
- break;
- }
- return rval;
- }
-
- /* Issue a prompt and read a line from the user */
- static int
- getline(sp,prompt,buf,n)
- struct session *sp;
- char *prompt;
- char *buf;
- int n;
- {
- /* If there's something already there, don't issue prompt */
- if(socklen(sp->input,0) == 0)
- tprintf(prompt);
-
- usflush(sp->output);
- return recvline(sp->input,buf,n);
- }
-
- /* Attempt to log in the user whose name is in ftp->username and password
- * in pass
- */
- static char *
- ftpcli_login(ftp,host)
- struct ftpcli *ftp;
- char *host; {
-
- char buf[80],*cp,*cp1;
- FILE *fp;
-
- extern char *Hostfile; /* List of user names and permissions */
-
- if((fp = fopen(Hostfile,"r")) == NULLFILE){
- return NULLCHAR;
- }
- while(fgets(buf,sizeof(buf),fp),!feof(fp)){
- buf[strlen(buf)-1] = '\0'; /* Nuke the newline */
- if(buf[0] == '#')
- continue; /* Comment */
- if((cp = strchr(buf,' ')) == NULLCHAR)
- /* Bogus entry */
- continue;
- *cp++ = '\0'; /* Now points to user name */
- if(strcmp(host,buf) == 0)
- break; /* Found host name */
- }
- if(feof(fp)){
- /* User name not found in file */
- fclose(fp);
- return NULLCHAR;
- }
- fclose(fp);
- /* Look for space after user field in file */
- if((cp1 = strchr(cp,' ')) == NULLCHAR)
- /* if not there then we'll prompt */
- ftp->password = NULLCHAR;
- else
- *cp1++ = '\0'; /* Now points to password */
- if(strcmp(cp,"*") == 0)
- cp1 = "anonymous";
- ftp->password = strdup(cp1);
- return strdup(cp);
- }
-
- int
- dolcd(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- register struct ftpcli *ftp;
-
- ftp = (struct ftpcli *)p;
- if(ftp == NULLFTP){
- tprintf(Notsess);
- return 1;
- }
-
- if(argc > 1){
- if (!dir_ok(argv[1],ftp->curdirs)) {
- tprintf("Invalid Drive/Directory - %s\n",argv[1]);
- return 1;
- }
-
- }
- tprintf("Local Directory - %s\n",ftp->curdirs->dir);
-
- return 0;
- }
-
-
- int
- doldir(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- register struct ftpcli *ftp;
- char ** margv;
- char path[128],*q;
-
- margv=(char **)callocw(2,sizeof(char*));
-
- ftp = (struct ftpcli *)p;
- if(ftp == NULLFTP){
- tprintf(Notsess);
- return 1;
- }
-
- tprintf("\n");
- if (argc == 1)
- margv[1]=strdup(ftp->curdirs->dir);
- else
- margv[1]=strdup(make_dir_path(argc,argv[1],ftp->curdirs->dir));
- dodir(2,margv,p);
- free(margv[1]);
- free(margv);
- tprintf("\n");
- return 0;
- }
-
- int
- dolmkdir(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- register struct ftpcli *ftp;
- char *buf;
-
- ftp = (struct ftpcli *)p;
- if(ftp == NULLFTP){
- tprintf(Notsess);
- return 1;
- }
- /* undosify(argv[1]); done in make_fname */
- buf=strdup(make_fname(ftp->curdirs->dir,argv[1]));
- if (mkdir(buf) == -1)
- tprintf("Can't make %s: %s\n",buf,sys_errlist[errno]);
- else
- tprintf("Directory %s Created\n",buf);
- free(buf);
- return 0;
- }
-
- int
- dolrmdir(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- register struct ftpcli *ftp;
- char *buf;
-
- ftp = (struct ftpcli *)p;
- if(ftp == NULLFTP){
- tprintf(Notsess);
- return 1;
- }
- buf=strdup(make_fname(ftp->curdirs->dir,argv[1]));
- if (rmdir(buf) == -1)
- tprintf("Can't remove %s: %s\n",buf,sys_errlist[errno]);
- else
- tprintf("Directory %s Removed\n",buf);
- free(buf);
- return 0;
- }
-
- #endif
-